package org.nimi317.web_gis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.nimi317.web_gis.Enum.InterpolateEnum;
import org.nimi317.web_gis.form.post.InterpolateIdwPost;
import org.nimi317.web_gis.form.post.InterpolatePost;
import org.nimi317.web_gis.form.post.InterpolateSearchPost;
import org.nimi317.web_gis.form.post.Page;
import org.nimi317.web_gis.dao.InterpolateDao;
import org.nimi317.web_gis.entity.Idw;
import org.nimi317.web_gis.entity.Interpolate;
import org.nimi317.web_gis.entity.Kriging;
import org.nimi317.web_gis.service.IdwService;
import org.nimi317.web_gis.service.InterpolateService;
import org.nimi317.web_gis.service.KrigingService;
import org.nimi317.web_gis.utils.ImageUtils;
import org.nimi317.web_gis.utils.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 插值(Interpolater)表服务实现类
 *
 * @author makejava
 * @since 2024-05-07 13:33:03
 */
@Service("interpolateService")
@Transactional
public class InterpolateServiceImpl extends ServiceImpl<InterpolateDao, Interpolate> implements InterpolateService {

    private final KrigingService krigingService;

    private final ImageUtils imageUtils;

    private final IdwService idwService;

    public InterpolateServiceImpl(KrigingService krigingService, ImageUtils imageUtils, IdwService idwService) {
        this.krigingService = krigingService;
        this.imageUtils = imageUtils;
        this.idwService = idwService;
    }

    @Override
    public void saveInterpolate(InterpolatePost interpolate, MultipartFile file) {
        // 根据参数查询是否存在
        Date time = interpolate.getTime();
        InterpolateEnum type = interpolate.getType();

        Integer id = krigingService.isExist(interpolate.getParam());

        //保存图像
        String url = imageUtils.save(file, type, time, id);

        // 保存插值结果
        this.save(new Interpolate(time, type, id, url, null));
    }

    @Override
    public void saveInterpolate(InterpolateIdwPost interpolateIdwPost, MultipartFile file) {

        Date time = interpolateIdwPost.getTime();

        InterpolateEnum type = interpolateIdwPost.getType();

        Integer id = idwService.isExist(interpolateIdwPost.getParam());

        //保存图像
        String url = imageUtils.save(file, type, time, id);

        // 保存插值结果
        this.save(new Interpolate(time, type, id, url, null));
    }

    @Override
    public String searchInterpolate(InterpolateSearchPost interpolatePost) {
        InterpolateEnum type = interpolatePost.getType();
        Integer id = krigingService.isExistAndGetId(interpolatePost.getParam());
        return getUrl(id, type, interpolatePost.getTime());
    }

    @Override
    public String searchInterpolate(InterpolateIdwPost interpolatePost) {
        InterpolateEnum type = interpolatePost.getType();
        Integer id = idwService.isExistAndGetId(interpolatePost.getParam());
        return getUrl(id, type, interpolatePost.getTime());
    }

    private String getUrl(Integer id, InterpolateEnum type, Date interpolatePost) {
        if (id != null) {
            LambdaQueryWrapper<Interpolate> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(Interpolate::getUrl).eq(Interpolate::getType, type)
                    .eq(Interpolate::getTime, interpolatePost)
                    .eq(Interpolate::getParam, id);
            Interpolate one = this.getOne(wrapper);
            if (one != null) {
                return one.getUrl();
            }
        }
        return null;
    }

    @Override
    public IPage<Interpolate> pageInterpolate(Page page) {
        IPage<Interpolate> paged = this.page(null, null);
        List<Integer> kriging = new ArrayList<>();
        List<Integer> idw = new ArrayList<>();
        List<Interpolate> records = paged.getRecords();
        for (Interpolate record : records) {
            switch (record.getType()) {
                case Kriging -> kriging.add(record.getParam());
                case Idw -> idw.add(record.getParam());
            }
        }
        List<Kriging> krigings = krigingService.listByIds(kriging);
        List<Idw> idws = idwService.listByIds(idw);
        Map<Object, Object> krigingsMap = MapUtils.listToMap(krigings, Kriging::getId);
        Map<Object, Object> idwsMap = MapUtils.listToMap(idws, Idw::getId);
        List<Interpolate> result = records.stream().peek(interpolate -> {
            Object o = null;
            switch (interpolate.getType()) {
                case Kriging -> o = krigingsMap.get(interpolate.getParam());
                case Idw -> o = idwsMap.get(interpolate.getParam());
            }
            interpolate.setParams(o);
        }).toList();
        paged.setRecords(result);
        return paged;
    }
}

